﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Interactivity;
using System.Windows.Media;
using GameLogic.Controls;

namespace GameLogic.Logic
{
    // Finds the GameLoop behavior of a game in which given contextElement is placed 
    public class GameLoopFinder
    { 
        private GameLoop gameLoop;
        public event EventHandler OnGameLoopLoaded;

        public GameLoop GameLoop
        {
            get { return this.gameLoop; }
        }

        public GameLoopFinder(FrameworkElement contextElement)
        {
            if (contextElement.Parent != null 
                || Application.Current.RootVisual != null && Application.Current.RootVisual.Equals(contextElement))
            {
                this.FindGameLoop(contextElement);
            }
            else
            {
                contextElement.Loaded += this.OnContextElementLoaded;
            }
        }

        private void OnContextElementLoaded(object sender, RoutedEventArgs e)
        {
            this.FindGameLoop((FrameworkElement)sender);
        }

        private void FindGameLoop(FrameworkElement contextElement)
        {
            FrameworkElement parent = contextElement;
            while (parent != null)
            {
                BehaviorCollection behaviors = Interaction.GetBehaviors(parent);

                this.gameLoop = (GameLoop)(from behavior in behaviors
                                           where typeof(GameLoop).IsAssignableFrom(behavior.GetType())
                                           select behavior).FirstOrDefault();

                if (this.gameLoop != null)
                {
                    if (this.OnGameLoopLoaded != null)
                    {
                        this.OnGameLoopLoaded(this, EventArgs.Empty);
                    }
                    break;
                }
                parent = VisualTreeHelper.GetParent(parent) as FrameworkElement;
            }
        }
    }
}
